package aes

import (
	"github.com/go-playground/validator/v10"
	"github.com/pkg/errors"
)

// Crypto 定义 Crypto 接口
type Crypto interface {
	Encrypt(plainText []byte) (cipherText []byte, err error)
	Decrypt(cipherText []byte) (plainText []byte, err error)
}

// OperationMode 工作模式
type OperationMode string

const (
	ECB OperationMode = "ECB"
	CBC OperationMode = "CBC"
	CFB OperationMode = "CFB"
	OFB OperationMode = "OFB"
	CTR OperationMode = "CTR"
	GCM OperationMode = "GCM"
)

type Client struct {
	OperationMode OperationMode `validate:"required"`
	Key           []byte        `validate:"required"`
	Iv            []byte        `validate:"required"`
	Mode          PaddingMode
	Way           Way
}

// New 实例化一个client
func New(c *Client) (Crypto, error) {
	if err := validator.New().Struct(c); err != nil {
		return nil, errors.WithStack(err)
	}
	switch c.OperationMode {
	case ECB:
		return newAESCryptoECB(c.Key, c.Mode, c.Way)
	case CBC:
		return newAESCryptoCBC(c.Key, c.Iv, c.Mode, c.Way)
	case CFB:
		return newAESCryptoCFB(c.Key, c.Iv, c.Way)
	case OFB:
		return newAESCryptoOFB(c.Key, c.Iv, c.Way)
	case CTR:
		return newAESCryptoCTR(c.Key, c.Iv, c.Way)
	case GCM:
		return newAESCryptoGCM(c.Key, c.Iv, c.Way)
	}
	return nil, errors.New("Unknown Operation Mode ")
}
